package com.nova.android.tvlauncher.apkinstall

import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.pm.PackageInfo
import android.content.pm.PackageInstaller
import android.content.pm.PackageManager
import android.os.Build
import com.shudong.lib_base.ext.appContext
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.IOException
import java.io.OutputStream
import java.util.zip.ZipFile
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
import kotlin.jvm.java

private val installMutex = Mutex()
suspend fun String.installMyXapkWithMutex(): InstallResult {
    return installMutex.withLock {
        installMyXapk()
    }
}


suspend fun String.installMyXapk(): InstallResult = withContext(Dispatchers.IO) {
    // 验证文件路径
    val filePath = this@installMyXapk
    val inputFile = File(filePath)
    if (!inputFile.exists() || !inputFile.canRead()) {
        throw IllegalArgumentException("文件无效或不可读: $filePath")
    }
    val isXapk = inputFile.extension.equals("xapk", ignoreCase = true)
    val isApk = inputFile.extension.equals("apk", ignoreCase = true)
    if (!isXapk && !isApk) {
        throw IllegalArgumentException("仅支持 XAPK 或 APK 文件: $filePath")
    }


    // 定义 tempDir，初始为 null
    var tempDir: File? = null
    // 准备 APK 文件列表
    val apkFiles = if (isXapk) {
        val xapkFileName = inputFile.nameWithoutExtension
        tempDir = File(appContext.cacheDir, xapkFileName).apply {
            mkdirs()
        }
        try {
            ZipFile(inputFile).use { zipFile ->
                zipFile.entries().asSequence().forEach { entry ->
                    if (entry.name.endsWith(".apk") || entry.name.endsWith(".obb") || entry.name.endsWith(
                            ".json"
                        )
                    ) {
                        val outFile = File(tempDir, entry.name)
                        zipFile.getInputStream(entry).use { input ->
                            FileOutputStream(outFile).use { output ->
                                input.copyTo(output)
                            }
                        }
                    } else {
                    }
                }
            }
            tempDir?.listFiles()?.filter { it.extension == "apk" } ?: emptyList()
        } catch (e: IOException) {
            throw e
        }
    } else {
        listOf(inputFile)
    }

    // 验证 APK 文件
    if (apkFiles.isEmpty()) {
        throw IllegalStateException("未找到有效的 APK 文件")
    }


    // --- 新增：判断是否降级 ---
    // 这里只判断第一个 APK，若你有多 APK 可做调整
    // 寻找主 APK（优先 base.apk 或不含 config. 的 APK）
    val mainApk = apkFiles.firstOrNull { file ->
        val fileName = file.name
        fileName.equals("base.apk", ignoreCase = true) || !fileName.contains("config.", ignoreCase = true)
    } ?: apkFiles.first() // 回退到第一个 APK

    //println("当前的第一个APK的名字是：${mainApk.name}")

    // 解析 APK 的包名和版本号
    val pm = appContext.packageManager
    val packageArchiveInfo: PackageInfo? = pm.getPackageArchiveInfo(mainApk.absolutePath, PackageManager.GET_META_DATA)
    packageArchiveInfo?.applicationInfo?.sourceDir = mainApk.absolutePath
    packageArchiveInfo?.applicationInfo?.publicSourceDir = mainApk.absolutePath

    if (packageArchiveInfo == null) {
        throw IllegalStateException("无法解析 APK 包信息")
    }

    val newVersionCode = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
        packageArchiveInfo.longVersionCode
    } else {
        packageArchiveInfo.versionCode.toLong()
    }
    val packageName = packageArchiveInfo.packageName

    // 获取设备上已安装版本号
    val installedVersionCode = try {
        val installedPackageInfo = pm.getPackageInfo(packageName, 0)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) installedPackageInfo.longVersionCode else installedPackageInfo.versionCode.toLong()
    } catch (e: PackageManager.NameNotFoundException) {
        // 应用未安装
        -1L
    }

    // 判断是否为降级安装
    if (installedVersionCode > 0 && newVersionCode < installedVersionCode) {
        // 降级，先卸载旧版本
        packageName.uninstallMyApp()
    }

    // --- 安装流程保持不变 ---


    // 安装 APK 文件
    try {
        val packageInstaller = appContext.packageManager.packageInstaller
        val params =
            PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL)
        val sessionId = packageInstaller.createSession(params)
        val session = packageInstaller.openSession(sessionId)
        apkFiles.forEachIndexed { index, apkFile ->
            if (!apkFile.exists() || !apkFile.canRead() || apkFile.length() == 0L) {
                throw IllegalStateException("APK 文件无效: ${apkFile.absolutePath}")
            }
            val out: OutputStream = session.openWrite(apkFile.name, 0, apkFile.length())
            FileInputStream(apkFile).use { input ->
                input.copyTo(out)
            }
            session.fsync(out)
            out.close()
        }
        // 创建 PendingIntent，恢复原始逻辑
        val intent = Intent(appContext, InstallReceiver::class.java)
        val pendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            PendingIntent.getBroadcast(
                appContext, 0, intent,
                PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
            )
        } else {
            PendingIntent.getBroadcast(
                appContext, 0, intent,
                PendingIntent.FLAG_UPDATE_CURRENT
            )
        }
        val statusReceiver = pendingIntent.intentSender
        session.commit(statusReceiver)
        session.close()
        var result = InstallReceiver.resultChannel.receive()
        // 清理 Channel
        InstallReceiver.resultChannel.close()
        InstallReceiver.resultChannel = Channel(1)

        // 清理临时目录（仅 XAPK 需要）
        if (isXapk && tempDir != null) {
            try {
                tempDir.deleteRecursively()
            } catch (e: Exception) {
            }
        }
        result
    } catch (e: Exception) {
        InstallReceiver.resultChannel.close()
        InstallReceiver.resultChannel = Channel(1)
        if (isXapk && tempDir != null) {
            try {
                tempDir.deleteRecursively()
            } catch (e: Exception) {
            }
        }
        throw e
    }
}


suspend fun String.uninstallMyApp(): UnInstallResult = withContext(Dispatchers.IO) {
    val pkName = this@uninstallMyApp
    val packageInstaller = appContext.packageManager.packageInstaller
    val intent = Intent(appContext, UnInstallReceiver::class.java)
    val pendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        PendingIntent.getBroadcast(
            appContext, 0, intent,
            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
        )
    } else {
        PendingIntent.getBroadcast(
            appContext, 0, intent,
            PendingIntent.FLAG_UPDATE_CURRENT
        )
    }
    try {
        packageInstaller.uninstall(pkName, pendingIntent.intentSender)
        var result = UnInstallReceiver.resultChannel.receive()
        // 清理 Channel
        UnInstallReceiver.resultChannel.close()
        UnInstallReceiver.resultChannel = Channel(1)
        result
    } catch (e: Exception) {
        throw e
    }

}

/**
 * 判断是否已安装相同版本的应用
 * @param targetPackageName 目标应用的包名
 * @param targetVersionCode 需要比对的版本号（versionCode）
 * @return true表示已安装相同版本，false表示未安装或版本不同
 */
fun Context.isSameVersionInstalled(
    targetPackageName: String,
    targetVersionCode: Int
): Boolean {
    return try {
        val packageInfo = packageManager.getPackageInfo(targetPackageName, 0)
        packageInfo.versionCode == targetVersionCode
    } catch (e: PackageManager.NameNotFoundException) {
        false // 应用未安装
    } catch (e: Exception) {
        false // 其他异常（如权限不足）
    }
}
